#!/usr/bin/env python

#  Copyright (c) 2010
#  The Regents of the University of Michigan
#  All Rights Reserved

#  Permission is granted to use, copy, create derivative works, and
#  redistribute this software and such derivative works for any purpose,
#  so long as the name of the University of Michigan is not used in
#  any advertising or publicity pertaining to the use or distribution
#  of this software without specific, written prior authorization. If
#  the above copyright notice or any other identification of the
#  University of Michigan is included in any copy of any portion of
#  this software, then the disclaimer below must also be included.

#  This software is provided as is, without representation or warranty
#  of any kind either express or implied, including without limitation
#  the implied warranties of merchantability, fitness for a particular
#  purpose, or noninfringement.  The Regents of the University of
#  Michigan shall not be liable for any damages, including special,
#  indirect, incidental, or consequential damages, with respect to any
#  claim arising out of or in connection with the use of the software,
#  even if it has been or is hereafter advised of the possibility of
#  such damages.
import collections
import cPickle
import itertools
import sys

import rollup_hops

def get_found_vdos(target_fragments, found_keys):
  vdos = collections.defaultdict(int)
  assert len(target_fragments) % 50 == 0, 'passed VDOs do not have 50 fragments!'
  for (idx, (fragment_key, _)) in enumerate(target_fragments):
    if fragment_key in found_keys:
      vdos[idx / 50] += 1

  return sum(1 for vdo in vdos if vdos[vdo] >= 45)

def main(argv):
  node_rollups = [cPickle.load(open(filename)) for filename in argv[2:]]
  targets = eval(open(argv[1]).read())
  n = len(node_rollups)
  for k in xrange(1, n + 1):
    num_combinations = len(list(itertools.combinations(xrange(n), k)))
    total_found_vdos = 0
    total_total_stores = 0
    total_num_found_keys = 0
#    total_unique_keys = 0
    total_value_bytes = 0
    grand_total_bytes = 0
    bencoded_stores = 0
    bencoded_bytes = 0
    peer_record_stores = 0
    peer_record_bytes = 0
    unvanish_acceptable_stores = 0
    unvanish_acceptable_bytes = 0

    for items in itertools.combinations(node_rollups, k):
      combination_data = rollup_hops.rollup(items)
      total_found_vdos += get_found_vdos(targets, combination_data[0])
      total_num_found_keys += len(combination_data[0])
      total_total_stores += combination_data[1]
#      total_unique_keys += len(combination_data[2])
      total_value_bytes += combination_data[2]
      grand_total_bytes += combination_data[3]
      bencoded_stores += combination_data[4]
      bencoded_bytes += combination_data[5]
      peer_record_stores += combination_data[6]
      peer_record_bytes += combination_data[7]
      unvanish_acceptable_stores += combination_data[8]
      unvanish_acceptable_bytes += combination_data[9]

    total_found_vdos /= num_combinations
    total_total_stores /= num_combinations
    total_num_found_keys /= num_combinations
    #total_unique_keys /= num_combinations
    total_value_bytes /= num_combinations
    grand_total_bytes /= num_combinations
    bencoded_stores /= num_combinations
    bencoded_bytes /= num_combinations
    peer_record_stores /= num_combinations
    peer_record_bytes /= num_combinations
    unvanish_acceptable_stores /= num_combinations
    unvanish_acceptable_bytes /= num_combinations

    print '\nAcross all %d-combinations:' % k
    print '=' * 60
    print 'Average found VDOs: %d of %d (%f)' % (total_found_vdos, len(targets) / 50, float(total_found_vdos) / (len(targets) / 50))
    print 'Average found VDO fragments: %d of %d (%f)' % (total_num_found_keys, len(targets), float(total_num_found_keys) / len(targets))
    print 'Average values stored: %d' % total_total_stores
    #print 'Average unique keys seen: %d' % total_unique_keys
    print 'Average total bytes stored: %d' % grand_total_bytes
    print 'Average bencoded values stored: %d' % bencoded_stores
    print 'Average bencoded bytes stored: %d' % bencoded_bytes
    print 'Average peer record values stored: %d' % peer_record_stores
    print 'Average peer record bytes stored: %d' % peer_record_bytes
    print 'Average Unvanish-acceptable values stored: %d' % unvanish_acceptable_stores
    print 'Average Unvanish-acceptable bytes stored: %d' % unvanish_acceptable_bytes
    print 'Average bytes in interesting values: %d' % total_value_bytes

if __name__ == '__main__':
  main(sys.argv)
